<?php
/**
 * 模型抽象类
 *
 * 一个关于各种模型的基本行为类，每个模型都必须继承这个类的方法
 * @package     Class
 * @author      jerry <jerryjiang15@163.com>
 * @version     $ID$
 */

abstract class Model
{
	var $ins_data;
	var $db;
	var $table;
	var $in_var;
	var $tpl;
	var $upload;
	var $sys_conf_var;
	var $query;
	var $order;
	var $limit;
	var $db_insert_id;
	var $page;
	var $where = array();
	var $join = array();
	var $from = array();
	var $groupby  = array();
	var $having = array();
	var $table_suffix = '';
	var $last_id;

	/**
	 * 构造函数
	 * @global $this->db 数据库类
	 * @global $table 数据库表列表
	 *
	 * @return Null
	 */
	function __construct()
	{
		global $tpl,$sys_conf_var,$in_var,$upload,$logger,$admin_lang,$db;

		$this->db = $db = DBFactory::getDBConnection($sys_conf_var['db']);   //get a batabase instance
		//$this->db          	= $db;
		$this->table 		= $sys_conf_var['table'];
		$this->in_var 		= $in_var;
		$this->tpl 			= $tpl;
		$this->lang 		= $admin_lang;
		$this->upload 		= $upload;
		$this->sys_conf_var = $sys_conf_var;
		$this->last_id		= &$this->db_insert_id;
	}


	/**
	 * 加载类库文件
	 *
	 * @param string $class
	 */
	function loadClass($class)
	{
		$numargs = func_num_args();

		if($numargs == 1)
		{
			$this->$class = new $class();
		}
		else
		{
			$arg_list = func_get_args();

			for ($i = 0; $i < $numargs; $i++) {
				if($i > 0)
				{
					$args[] = '$arg_list[' . $i . ']';
				}
			}

			eval('$this->$class = new $class(' . implode(',',$args) . ');');
		}
	}

	/**
	 * 加载模型
	 *
	 * @param string $class
	 */
	function loadModel($class)
	{
		$numargs = func_num_args();

		if($numargs == 1)
		{
			$this->$class = new $class();
		}
		else
		{
			$arg_list = func_get_args();

			for ($i = 0; $i < $numargs; $i++) {
				if($i > 0)
				{
					$args[] = '$arg_list[' . $i . ']';
				}
			}

			eval('$this->$class = new $class(' . implode(',',$args) . ');');
		}
	}

	/**
	 * 添加处理数据
	 *
	 * @param string $var   变量名
	 * @param steing $value 值
	 * @param int    $modified  = 1 : 为添加修饰符
	 */
	function addData($var,$value = null,$modified = 1)
	{
		if (is_array($var))
		{
			foreach ($var as $key => $val)
			{
				if ($key != '')
				{
					$this->ins_data[$key] = $val;
					$this->modified[$key] = $modified;
				}
			}
		}
		else
		{
			$this->ins_data[$var] = $value;
			$this->modified[$var] = $modified;
		}
	}

	/**
	 * 修改数组里的值
	 *
	 * @param string $key
	 * @param string $val
	 */
	function chgData($key,$val)
	{
		$this->ins_data[$key] = $val;
	}

	/**
	 * 删除一个数据
	 *
	 * @param string $key
	 */
	function delData($key)
	{
		unset($this->ins_data[$key]);
	}

	/**
	 * 清空数据
	 *
	 */
	function cleanData()
	{
		unset($this->ins_data);
	}

	/**
	 * 清空条件
	 *
	 */
	function cleanConditions()
	{
		unset($this->where);
		unset($this->conditions);
		unset($this->from);
		unset($this->join);
		unset($this->join_table);
		unset($this->groupby);
		unset($this->groupby_where);
		unset($this->having);
		unset($this->having_where);
		unset($this->order);
		unset($this->limit);
	}

	/**
	 * 处理插入数据库字符串
	 *
	 * @param string $string
	 * @return string
	 */
	function ensql($string)
	{
		return addslashes($string);
	}

	/**
	 * 插入数据库数据
	 *
	 * @param string $table
	 * @return boolean
	 */
	function dataInsert($table)
	{
		try
		{
			//构建SQL语句
			$ins_data_num = count($this->ins_data);
			$foreach_i = 0;
			$query = "Insert into " . $this->getTable($table) . " \n(\n";
			$query_key = "";
			$query_val = "";

			foreach($this->ins_data as $key=>$val)
			{
				if(strlen($val)>0)
				{
					if($foreach_i == 0)
					{
						$query_key .= $key;

						if($this->modified[$key])
						{
							$query_val .= "'" . $this->ensql($val) . "'";
						}
						else
						{
							$query_val .= $this->ensql($val);
						}
					}
					else
					{
						$query_key .= ",\n{$key}";

						if($this->modified[$key])
						{
							$query_val .= ",\n'" . $this->ensql($val) . "'";
						}
						else
						{
							$query_val .= ",\n" . $this->ensql($val);
						}
					}

					$foreach_i = $foreach_i + 1;
				}
			}

			$query .= $query_key . "\n) \nValues \n(\n" . $query_val . "\n)";

			$this->cleanData();

			//SQL语句执行
			//echo $query;
			if($result = $this->db->Execute($query))
			{
				$this->db_insert_id = $this->db->getInsertID();
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 添加条件语句
	 *
	 * @param string $field  表字段
	 * @param string $value	 值
	 * @param string $terms  条件
	 * @param string $type  条件逻辑运算符
	 * @param string $modify  条件修饰符
	 */
	function where($field,$value,$terms = "=",$type = "and",$modify = 1)
	{
		$prefix = (count($this->where) == 0) ? '' : $type . ' ';

		if(strtolower($terms) == 'in' || strtolower($terms) == 'not in')
		{
			$this->where[] = $prefix . $field . ' ' . $terms . ' (' . $value . ')';
		}
		elseif(strtolower($terms) == 'like')
		{
			$this->where[] = $prefix . $field . ' ' . $terms . ' "%' . $value . '%"';
		}
		else
		{
			if($modify)
			{
				$value = "'" . $value . "'";
			}

			$this->where[] = $prefix . $field . ' ' . $terms . ' ' . $value;
		}

		$this->conditions = implode(" ",$this->where);
	}

	/**
	 * 解析表解析符
	 *
	 * @param string $table
	 * @return string
	 */
	function table_aliases($table)
	{
		$temp = explode(' ',$table);

		if(count($temp) > 1)
		{
			return $this->getTable($temp[0]) . ' ' . end($temp);
		}
		else
		{
			return $this->getTable($temp[0]);
		}
	}

	/**
	 * 得到表名
	 *
	 */
	function getTable($table)
	{
		if(!$this->table[$table]) die('this table does not exist - ' . $table);

		return $this->table[$table] . $this->table_suffix;
	}

	/**
	 * 设置多表查询
	 *
	 * @param string $table
	 */
	function from($table)
	{
		if (!$table = $this->table_aliases($table)) return false;

		$this->from[] = $table;

		$this->from_table = implode(",",$this->from);
	}




	/**
	 * join查询
	 *
	 * @param string $table
	 * @param string $cond
	 * @param string $type
	 */
	function join($table, $cond, $type = '')
	{
		if (!$table = $this->table_aliases($table)) return false;

		if ($type != '')
		{
			$type = strtoupper(trim($type));

			if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))
			{
				$type = '';
			}
			else
			{
				$type .= ' ';
			}
		}

		// Strip apart the condition and protect the identifiers
		if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match))
		{
			$cond = $match[1] . $match[2] . $match[3];
		}

		$this->join[] = $type . 'JOIN ' . $table . ' ON ' . $cond;

		$this->join_table = " " . implode(" ",$this->join);
	}

	/**
	 * 添加groupBy 条
	 *
	 * @param string $field
	 */
	function groupby($field)
	{
		$this->groupby[] = $field;

		$this->groupby_where = " GROUP BY " . implode(",",$this->groupby) . ' ';
	}

	/**
	 * 格式化要插入数据库的字段
	 * @param $data
	 * @return unknown_type
	 */
	function formatData($data)
	{
		if(is_array($data))
		{
			foreach($data as $key => $val)
			{
				$data[$key] = mysql_real_escape_string(strip_tags($val));
			}

			return $data;
		}
		else
		{
			return mysql_real_escape_string(strip_tags($data));
		}
	}

	/**
	 * @author hary
	 * @param array $arr
	 * @return array
	 */
	function toArray(&$obj){
		if(is_object($obj))
		{
			$obj = get_object_vars($obj);
		}
		else if(is_array($obj))
		{
			foreach($obj as &$item)
			{
				$this->toArray($item);
			}
		}
		return $obj;
	}

	/**
	 * @param $obj
	 * @return unknown_type
	 */
	function object2array($obj){
		$arr = array();

		if(is_object($obj))
		{
			$ar = get_object_vars($obj);

			foreach($ar as $k=>$a)
			{
				$arr[$k] = $a;
			}
		}
		return $arr;
	}

	/**
	 * 添加having 条
	 *
	 * @param string $field
	 */
	function having($field,$value,$terms = '=', $type = 'and')
	{
		$prefix = (count($this->having) == 0) ? '' : $type . ' ';

		if (is_null($value))
		{
			$value = ' IS NULL';
		}

		if(!is_integer($value))
		{
			$value = "'" . $value . "'";
		}


		if(strtolower($terms) == 'in' || strtolower($terms) == 'not in')
		{
			$this->having[] = $prefix . $field . ' ' . $terms . ' (' . $value . ')';
		}
		else
		{
			$this->having[] = $prefix . $field . ' ' . $terms . ' ' . $value;
		}

		$this->having_where = " HAVING " . implode(" ",$this->having) . ' ';
	}

	/**
	 * 设置记录上限
	 *
	 * @param int $limit
	 */
	function setLimit($limit)
	{
		if ($limit) $this->limit = $limit;
	}

	/**
	 * 设置排序
	 *
	 * @param string $order
	 */
	function setOrder($order = ' order by ID desc')
	{
		$this->order = " " . $order . " ";
	}

	/**
	 * 设置取得的页数
	 *
	 * @param int $page
	 */
	function setPage($page)
	{
		$this->page = $page;
	}

	/**
	 * 更新数据库数据
	 *
	 * @param string $table 表名
	 * @param string $where 查询条件
	 * @return boolean
	 */
	function dataUpdate($table)
	{
		try
		{
			//构建SQL语句
			$foreach_i = 0;
			$query     = "update " . $this->getTable($table) . " set ";
			$query_key = "";
			$query_val = "";
			$where = $this->conditions ? ' where ' . $this->conditions : '';

			foreach($this->ins_data as $key=>$val)
			{
				if($foreach_i == 0)
				{
					$query_key = "{$key}";

					if($this->modified[$key])
					{
						$query_val = "='" . $this->ensql($val) . "'";
					}
					else
					{
						$query_val = "=" .$this->ensql($val);
					}

					$query .= $query_key . $query_val;
				}
				else
				{
					$query_key = ",{$key}";

					if($this->modified[$key])
					{
						$query_val = "='" .  $this->ensql($val) . "'";
					}
					else
					{
						$query_val = "=" . $this->ensql($val);
					}

					$query .= $query_key . $query_val;
				}

				$foreach_i = $foreach_i + 1;
			}

			$query .= " $where";

			$this->cleanConditions();
			$this->cleanData();
			//echo $query;exit;
			//SQL语句执行
			if($this->db->query($query))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 删除数据
	 *
	 * @param string $table
	 * @param string $which
	 * @param string $id
	 * @param string $method
	 * @return boolean
	 */
	function dataDel($table)
	{
		$where = $this->conditions ? ' where ' . $this->conditions : '';

		try
		{
			/**Modified by jefurry*/
			if(isset($this->order))
			{
				$order = ' ' . $this->order;
			}

			if(isset($this->page) && isset($this->limit))
			{
				$offset = ($this->page - 1) * $this->limit;
				$limit = ' limit ' . $this->limit;

				$this->page_limit = $limit;
			}
			//构建SQL语句
			$query = "Delete From " . $this->getTable($table)
			. $where
			. $order
			. $this->page_limit;/**Modified by jefurry*/

			$this->cleanConditions();

			if($this->db->Execute($query))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 取得记录数量
	 *
	 * @param string $table  传入的数据表
	 * @param string $where  查询条件
	 * @return int   传回记录条数
	 */
	function dataNum($table)
	{
		$this->from($table);

		$where = $this->conditions ? ' where ' . $this->conditions : '';
		$this->cleanConditions();

		try
		{
			$sql = "select count(*) as Num from " . $this->from_table . $where;
			$result = $this->db->getRow($sql);
			return $result['Num'];
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 得到一组数据
	 *
	 * @param string $table  数据表名
	 * @param string $where  查询条件
	 * @param string $select  查询字段
	 * @param string $sql  自定义sql语句,当$sql存在是,前面参数无效
	 * @return array      得到一条记录
	 */
	function getDataInfo($table,$select = '*')
	{
		$this->from($table);

		$where = $this->conditions ? ' where ' . $this->conditions : '';

		try
		{
			$sql = $sql ? $sql : "select " . $select ." from "
			. $this->from_table
			. $this->join_table
			. $where
			. $this->groupby_where
			. $this->having_where
			. $this->order;

			$this->cleanConditions();

			$result = $this->db->getRow($sql);

			return $this->unformatDate($result);
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 反译数据库记录
	 * @param $result
	 * @return unknown_type
	 */
	function unformatDate($result)
	{
		if( !empty( $result ) )
		{
			foreach($result as $key=>&$value )
			{
				$result[$key] = stripslashes( $value );
			}
		}

		return $result;
	}

	/**
	 * 得到数据列表
	 *
	 * @param string $table  数据表名
	 * @param string $select  查询字段
	 * @return array   返回数据记录列表
	 */
	function getDataList($table,$select = '*')
	{
		$this->from($table);

		$where = $this->conditions ? ' where ' . $this->conditions : '';

		if(isset($this->order))
		{
			$order = ' ' . $this->order;
		}

		if(isset($this->page) && isset($this->limit))
		{
			$offset = ($this->page - 1) * $this->limit;
			$limit = ' limit ' . $this->limit . ' offset ' . $offset;

			$this->page_limit = $this->limit;
		}

		try
		{
			$this->query = "select " . $select . " from " . $this->from_table
			. $this->join_table
			. $where
			. $this->groupby_where
			. $this->having_where
			. $order
			. $limit;

			$this->cleanConditions();

			$result = $this->db->Execute($this->query);

			while(!$result->EOF)
			{
				$list[] = $this->unformatDate($result->fields);
				$result->moveNext();
			}

			return $list;
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 自定义查询
	 *
	 * @param string $sql 查询语句
	 * @param int $type 返回类型 1=多条记录，2=单条记录
	 * @return array
	 */
	function customQuery($sql,$type = 1)
	{

		if(isset($this->order))
		{
			$order = ' ' . $this->order;
		}

		if(isset($this->page) && isset($this->limit))
		{
			$offset = ($this->page - 1) * $this->limit;
			$limit = ' limit ' . $this->limit . ' offset ' . $offset;

			$this->page_limit = $this->limit;
		}

		$this->query = $sql.$order.$limit;

		try
		{
			if($type == 1)
			{
				$result = $this->db->Execute($this->query);

				while(!$result->EOF)
				{
					$list[] = $result->fields;
					$result->moveNext();
				}

				return $list;
			}
			else
			{
				$result = $this->db->getRow($this->query);

				return $result;
			}
		}
		catch (MySqlException $e)
		{
			$e->showError();
		}
	}

	/**
	 * 得到上一个多记录查询语句的总记录数和总页数
	 *
	 * @param string $url  分页链接地址
	 */
	function getPageInfo($url,$showPages = 5)
	{
		if ($this->query)
		{
			$pattern 			= '/select (.*?) from (.*)limit(.*)/i';
			$replacement 		= 'select count(*) as num from $2';
			$count_query 		= preg_replace($pattern, $replacement, $this->query);

			try
			{
				$result = $this->db->getRow($count_query);
			}
			catch (MySqlException $e)
			{
				$e->showError();
			}

			$page = $this->_getPageInfo($url, $result['num'], $this->page_limit, $this->page,$showPages);

			unset($this->page_limit);
			unset($this->page);

			return $page;
		}
		else
		{
			return -1;
		}
	}

	/**
	 * 生成页面列表
	 * @param $url
	 * @param $total
	 * @param $page_size
	 * @param $page
	 * @param $showPages
	 * @return unknown_type
	 */
	function _getPageInfo($url,$total,$page_size,$page,$showPages=5)
	{
		$page_info['result_num']   = $total;
		$page_info['page_num']     = ceil($total/$page_size);
		$page_info['current_page'] = $page;
		$page_info['page']         = page($page_info['page_num'],$page,$url,$showPages);

		return $page_info;
	}

	/**
	 *去除指定字段
	 */
	function addDataBatch( $data, $skip_key = '' )
	{
		foreach( $data AS $key => $value )
		{
			if ($skip_key != $key) $this->addData( "`{$key}`", $value );
		}
	}

	/**
	 * 批量添加数据，含字段过滤
	 * @param Array $data = array('id' => 213, 'name' => '张三' ...)
	 * @param unknown_type $allow_key_list array('id', 'name')
	 */
	function addDataBatch2($data, $allow_key_list)
	{
		foreach( $data AS $key => $value )
		{
			if(in_array($key, $allow_key_list)) $this->addData( "`{$key}`", $value );
		}
	}

	/**
	 * 将键值对转成sql语句
	 * @param $condition
	 * @return unknown_type
	 */
	function setBatchWhere($condition)
	{
		foreach($condition AS $key => $value)
		{
			$this->where($key, $value);
		}
	}

	/**
	 * 选择用户数据库，当查询用户分库时使用
	 *
	 * @param int $uid 用户id,uid为0选择公共数据库
	 */
	function selectUserDB($uid)
	{
		if(!$uid)
		{
			return false;
		}
		else
		{
			$this->db->selectDB($this->sys_conf_var['db']['db_name'] . '_user_' . $this->get_db_num($uid));

			$this->table_suffix = '_' . $this->get_tb_num($uid);
		}
	}

	function selectMainDB()
	{
		$this->db->selectDB($this->sys_conf_var['db']['db_name']);

		$this->table_suffix = '';
	}


	/**
	 * 路由数据库
	 *
	 * @param int $uid
	 * @return int
	 */
	function get_db_num($uid)
	{
		$num = @floor(($uid%10000)/100);

		return $num;
	}

	/**
	 * 路由数据表
	 *
	 * @param unknown_type $uid
	 * @return unknown
	 */
	function get_tb_num($uid)
	{
		$num = @floor(($uid%10000)%100);

		return $num;
	}
}


/**
 * $Log$
 */
?>